
function mod289(v4)
{
	var t = new vec4();
	vec4scale(t, v4, 1.0/289.0);
	t.floor();
	t.scale(289.0);
	vec4sub(t, v4, t);
	return t;

	//return x.vecsub(x * (1.0f / 289.0)) * 289.0;
}
 
function permute(x)
{
	var t = new vec4();
	vec4scale(t, x, 34.0);
	vec4addscalar(t, t, 1.0);
	vec4mul(t, t, x);
	return mod289(t);
	//return mod289(((x*34.0f)+1.0f)*x);
}

 
function taylorInvSqrt(r) {
	var t = r.copy();
	t.scale(-0.85373472095314);
	t.add(1.79284291400159);
	return t;
    	//return 1.79284291400159f -  0.85373472095314f* r;
}
 
function fade(t) {
	var tpow3 = t.copy();
	tpow3.mulvec(t);
	tpow3.mulvec(t);

	var t2 = t.copy();
	t2.madscalar(6.0, -15.0);
	
	vec2mad(t2, t, t2, new vec2(10.0,10.0));

	return tpow3.mulvec(t2);
	
    	//return t*t*t*(t*(t*6.0f-15.0f)+10.0f);
}

 
function mix(a, b, t) {
	return a*(1.0 - t) + b*t;
}
// Classic Perlin noise
function cnoise(P) {

	var t = new vec4(P.x, P.y, P.x, P.y);
	var t2 = new vec4(0.0,0.0,1.0,1.0);
	
	var Pi = new vec4(), Pf = new vec4();
	vec4floor(Pi, t);
	Pi.addvec(t2);

	vec4frac(Pf, t);
	Pf.subvec(t2);
    
	Pi = mod289(Pi); // To avoid truncation effects in permutation

    	var ix = new vec4(Pi.x, Pi.z, Pi.x, Pi.z);
    	var iy = new vec4(Pi.y, Pi.y, Pi.w, Pi.w);
    	var fx = new vec4(Pf.x, Pf.z, Pf.x, Pf.z);
    	var fy = new vec4(Pf.y, Pf.y, Pf.w, Pf.w);

	t = permute(ix);
	vec4add(t, t, iy); 
    	t = permute(t);

	var gx, gy, tx;
    	//var gx = fract(i * (1.0f / 41.0f)) * 2.0f - 1.0f;
	t.scale(1.0/41.0);
	t.frac();
	t.scale(2.0);
	t.sub(1.0);
	gx = t.copy();

	gy = new vec4();
	vec4abs(gy, gx);
	gy.sub(0.5); 
    	//var gy = abs(gx) - 0.5f ;

	tx = gx.copy();
	tx.add(0.5);
	tx.floor();
   	//var tx = floor(gx + 0.5f);

	vec4sub(gx, gx, tx);
    	//gx = gx - tx;

    	var g00 = new vec2(gx.x,gy.x);
    	var g10 = new vec2(gx.y,gy.y);
    	var g01 = new vec2(gx.z,gy.z);
    	var g11 = new vec2(gx.w,gy.w);

    	norm = taylorInvSqrt(new vec4(g00.lengthsq(), g01.lengthsq(), g10.lengthsq(), g11.lengthsq()));
    	g00.scale(norm.x);  
    	g01.scale(norm.y);  
    	g10.scale(norm.z);  
    	g11.scale(norm.w);  

    	var n00 = vec2dot(g00, new vec2(fx.x, fy.x));
    	var n10 = vec2dot(g10, new vec2(fx.y, fy.y));
    	var n01 = vec2dot(g01, new vec2(fx.z, fy.z));
    	var n11 = vec2dot(g11, new vec2(fx.w, fy.w));

    	var fade_xy = fade(new vec2(Pf.x, Pf.y));
    	var n_x = new vec2();
	vec2mix(n_x, new vec2(n00, n01), new vec2(n10, n11), fade_xy.x);
    	var n_xy = mix(n_x.x, n_x.y, fade_xy.y);
    	return 2.3 * n_xy;
}
/*
float cnoise(P)
{
    var Pi = floor(vec4(P.x, P.y, P.x, P.y)) + vec4(0.0f, 0.0f, 1.0f, 1.0f);
    var Pf = fract(vec4(P.x, P.y, P.x, P.y)) - vec4(0.0f, 0.0f, 1.0f, 1.0f);
    Pi = mod289(Pi); // To avoid truncation effects in permutation
    var ix = new vec4(Pi.x, Pi.z, Pi.x, Pi.z);
    var iy = new vec4(Pi.y, Pi.y, Pi.w, Pi.w);
    var fx = new vec4(Pf.x, Pf.z, Pf.x, Pf.z);
    var fy = new vec4(Pf.y, Pf.y, Pf.w, Pf.w);
     
    vec4 i = permute(permute(ix) + iy);
     
    vec4 gx = fract(i * (1.0f / 41.0f)) * 2.0f - 1.0f;
    vec4 gy = abs(gx) - 0.5f ;
    vec4 tx = floor(gx + 0.5f);
    gx = gx - tx;
     
    vec2 g00 = vec2(gx.x,gy.x);
    vec2 g10 = vec2(gx.y,gy.y);
    vec2 g01 = vec2(gx.z,gy.z);
    vec2 g11 = vec2(gx.w,gy.w);
     
    vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
    g00 *= norm.x;  
    g01 *= norm.y;  
    g10 *= norm.z;  
    g11 *= norm.w;  
     
    float n00 = dot(g00, vec2(fx.x, fy.x));
    float n10 = dot(g10, vec2(fx.y, fy.y));
    float n01 = dot(g01, vec2(fx.z, fy.z));
    float n11 = dot(g11, vec2(fx.w, fy.w));
     
    vec2 fade_xy = fade(vec2(Pf.x, Pf.y));
    vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
    float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
    return 2.3f * n_xy;
}
*/
/* 
// Classic Perlin noise, periodic variant
float pnoise(vec2 P, vec2 rep)
{
    vec4 Pi = floor(vec4(P.x, P.y, P.x, P.y)) + vec4(0.0f, 0.0f, 1.0f, 1.0f);
    vec4 Pf = fract(vec4(P.x, P.y, P.x, P.y)) - vec4(0.0f, 0.0f, 1.0f, 1.0f);
    Pi = mod(Pi, vec4(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period
    Pi = mod289(Pi);        // To avoid truncation effects in permutation
    vec4 ix = vec4(Pi.x, Pi.z, Pi.x, Pi.z);
    vec4 iy = vec4(Pi.y, Pi.y, Pi.w, Pi.w);
    vec4 fx = vec4(Pf.x, Pf.z, Pf.x, Pf.z);
    vec4 fy = vec4(Pf.y, Pf.y, Pf.w, Pf.w);
          
    vec4 i = permute(permute(ix) + iy);
     
    vec4 gx = fract(i * (1.0f / 41.0f)) * 2.0f - 1.0f ;
    vec4 gy = abs(gx) - 0.5f ;
    vec4 tx = floor(gx + 0.5f);
    gx = gx - tx;
     
    vec2 g00 = vec2(gx.x,gy.x);
    vec2 g10 = vec2(gx.y,gy.y);
    vec2 g01 = vec2(gx.z,gy.z);
    vec2 g11 = vec2(gx.w,gy.w);
     
    vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
    g00 *= norm.x;  
    g01 *= norm.y;  
    g10 *= norm.z;  
    g11 *= norm.w;  
     
    float n00 = dot(g00, vec2(fx.x, fy.x));
    float n10 = dot(g10, vec2(fx.y, fy.y));
    float n01 = dot(g01, vec2(fx.z, fy.z));
    float n11 = dot(g11, vec2(fx.w, fy.w));
     
    vec2 fade_xy = fade(vec2(Pf.x, Pf.y));
    vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
    float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
    return 2.3f * n_xy;
}
*/

function fbm(v2_P, ioctaves, flacunarity, fgain) {
//float fbm(vec2 P, int octaves, float lacunarity, float gain)
    sum = 0.0;
    amp = 1.0;
    pp = v2_P;
     
    var i;
     
    for(i = 0; i < ioctaves; i+=1)
    {
        amp *= fgain;
        sum += amp * cnoise(pp);
        pp.scale(flacunarity);
    }
    return sum;
 
}
 
/* 
float pattern(vec2 p) {
    float l = 2.5f;
    float g = 0.4f;
    int oc = 10;
     
    vec2 q = vec2( fbm( p + vec2(0.0,0.0),oc,l,g),fbm( p + vec2(5.2f,1.3f),oc,l,g));
    vec2 r = vec2( fbm( p + 4.0f*q + vec2(1.7f,9.2f),oc,l,g ), fbm( p + 4.0f*q + vec2(8.3f,2.8f) ,oc,l,g));
    return fbm( p + 4.0f*r ,oc,l,g);    
}
 
float pattern2( vec2 p, vec2& q, vec2& r , float time)
{
    float l = 2.3f;
    float g = 0.4f;
    int oc = 10; 
     
    q.x = fbm( p + vec2(time,time),oc,l,g);
    q.y = fbm( p + vec2(5.2f*time,1.3f*time) ,oc,l,g);
     
    r.x = fbm( p + 4.0f*q + vec2(1.7f,9.2f),oc,l,g );
    r.y = fbm( p + 4.0f*q + vec2(8.3f,2.8f) ,oc,l,g);
     
    return fbm( p + 4.0f*r ,oc,l,g);
}
*/
